package start.doubudouyin.websocket;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import start.doubudouyin.entity.Usersmessage;
import start.doubudouyin.service.FollowService;
import start.doubudouyin.service.UsersmessageService;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/chat/{userId}")
@Component
public class ChatEndpoint {

    private static final Map<String, Session> onlineUsers = new ConcurrentHashMap<>();

    private static UsersmessageService usersmessageService;
    private static FollowService followService;

    @Autowired
    public void setUsersmessageService(UsersmessageService usersmessageService) {
        ChatEndpoint.usersmessageService = usersmessageService;
    }
    @Autowired
    public void setFollowService(FollowService followService) {
        ChatEndpoint.followService = followService;
    }

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId) {
        if (userId != null) {
            onlineUsers.put(userId, session);

            // 异步通知关注者该用户已上线
            CompletableFuture.runAsync(() -> {
                notifyFollowersOnline(userId);
            });
        }
    }

    @OnMessage
    public void onMessage(String jsonMessage) {
        CompletableFuture.runAsync(() -> {
            try {
                JSONObject messageObj = JSON.parseObject(jsonMessage);
                String type = messageObj.getString("type");
                if ("message".equals(type)) {
                    // 处理普通聊天消息
                    handleChatMessage(jsonMessage);
                }
                // 可以添加其他消息类型处理
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }

    @OnClose
    public void onClose(Session session, @PathParam("userId") String userId) {
        // 异步通知关注者该用户已下线
        CompletableFuture.runAsync(() -> {
            notifyFollowersOnline(userId);
        });
        onlineUsers.entrySet().removeIf(entry -> entry.getValue().equals(session));

    }

    @OnError
    public void onError(Session session, Throwable error) {
        onlineUsers.entrySet().removeIf(entry -> entry.getValue().equals(session));
        throw new RuntimeException(error);
    }

    // 处理消息
    public void handleChatMessage(String jsonMessage) {
        Usersmessage message = JSON.parseObject(jsonMessage, Usersmessage.class);
        // 保存到数据库
        Usersmessage dbMessage = new Usersmessage();
        dbMessage.setSenderId(message.getSenderId());
        dbMessage.setReceiverId(message.getReceiverId());
        dbMessage.setContent(message.getContent());
        dbMessage.setSendTime(new Date());
        usersmessageService.insertUsersMessage(dbMessage);
        //修改chat字段
        followService.updatechat(message.getSenderId(),message.getReceiverId());

        // 异步转发消息
        // 从在线用户Map中获取接收者的Session
        Session receiverSession = onlineUsers.get(message.getReceiverId());
        // 如果接收者在线且Session是打开的，则异步发送消息
        if (receiverSession != null && receiverSession.isOpen()) {
            // 异步发送消息
            receiverSession.getAsyncRemote().sendText(jsonMessage);
        }
    }

    /**
     * 通知关注者用户上线
     * @param userId 刚上线的用户ID
     */
    private void notifyFollowersOnline(String userId) {
        // 1. 获取该用户的所有关注者
        List<String> followerIds = followService.getFollowers(userId);

        // 2. 构建上线通知消息
        JSONObject onlineMsg = new JSONObject();
        onlineMsg.put("type", "online");
        onlineMsg.put("userId", userId);
        onlineMsg.put("timestamp", System.currentTimeMillis());

        String message = onlineMsg.toJSONString();

        // 3. 向每个在线关注者发送通知
        followerIds.forEach(followerId -> {
            Session followerSession = onlineUsers.get(followerId);
            if (followerSession != null && followerSession.isOpen()) {
                followerSession.getAsyncRemote().sendText(message);
            }
        });
    }
}